/* os_cfgfile.c : os config file operation
 * CopyRight (C) 2008 dgnbbs
 * drangon_zhou@21cn.com
 * 2008-10
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "os_cfgfile.h"

#include <stdio.h>
#include <string.h>

struct os_cfg_t_t
{
	char * name;
	char * val;
	struct os_cfg_t_t * next;
};


os_cfg_t os_cfg_open( const char * cfgfile )
{
	char buf[1024];
	int linenum;
	FILE * fp;
	struct os_cfg_t_t * cfg;
	struct os_cfg_t_t * last;
	struct os_cfg_t_t * tmpcfg;

	if( (fp = fopen( cfgfile, "r" )) == NULL ) {
		PR_ERR( "open file [%s], errno %d", cfgfile, errno );
		return NULL;
	}

	linenum = 0;
	cfg = last = NULL;
	while( fgets( buf, sizeof(buf), fp ) != NULL ) {
		int n;
		char * name;
		char * val;

		linenum ++;

		// <1> read name and value;
		n = strspn( buf, " \t" );
		name = buf + n;
		if( *name == '#' || *name == '\r' || *name == '\n' || *name == '\n' )
			continue;
		n = strcspn( name, " \t" );
		if( name[n] == '\0' ) {
			PR_WARN( "ignore bad line %d : [%s]", linenum, buf );
			continue;
		}
		name[n] = '\0';
		val = name + n + 1;
		n = strspn( val, " \t" );
		val += n;
		n = strcspn( val, " \t" );
		if( n == 0 ) {
			PR_WARN( "ignore bad line %d : [%s]", linenum, buf );
			continue;
		}
		val[n] = '\0';

		// <2> create config node
		tmpcfg = malloc( sizeof(*tmpcfg) );
		tmpcfg->name = strdup( name );
		tmpcfg->val = strdup( val );
		tmpcfg->next = NULL;
		if( cfg == NULL ) {
			cfg = last = tmpcfg;
		}
		else {
			last->next = tmpcfg;
			last = tmpcfg;
		}
	}

	fclose( fp );
	return (os_cfg_t)cfg;
}

int os_cfg_close( os_cfg_t cfg )
{
	struct os_cfg_t_t * p;
	struct os_cfg_t_t * tmp;
	p = cfg;
	while( p != NULL ) {
		tmp = p;
		p = p->next;

		free( p->name );
		free( p->val );
		free( p );
	}
	return 0;
}

const char * os_cfg_get( os_cfg_t cfg, const char * name )
{
	const struct os_cfg_t_t * p;
	for( p = cfg; p != NULL; p = p->next ) {
		if( strcmp( p->name, name ) == 0 )
			return p->val;
	}
	return NULL;
}

long os_cfg_getl( os_cfg_t cfg, const char * name, long default_val )
{
	long ret;
	const char * val = os_cfg_get( cfg, name );
	if( val != NULL ) {
		ret = atol( val );
	}
	else {
		ret = default_val;
	}
	return ret;
}

double os_cfg_getd( os_cfg_t cfg, const char * name, double default_val )
{
	double ret;
	const char * val = os_cfg_get( cfg, name );
	if( val != NULL ) {
		ret = atof( val );
	}
	else {
		ret = default_val;
	}
	return ret;
}

